package com.asen.commons.core.jdbc.builder.mysql;

import com.asen.commons.core.jdbc.builder.SqlBuilder;
import com.asen.commons.core.jdbc.param.ParamStatementSetter;
import com.asen.commons.core.jdbc.param.SqlContext;
import com.asen.commons.core.jdbc.param.SqlContextManager;
import com.asen.commons.core.meta.dao.Condition;
import com.asen.commons.core.meta.entity.FieldObject;
import com.asen.commons.utils.BaseAssert;
import com.asen.commons.utils.StringUtils;
import org.apache.commons.lang3.ArrayUtils;

import java.util.List;

/**
 * 更新数据SQL构建器
 *
 * @author Gary
 * @version 1.0
 * @date 2018-11-28
 */
public class UpdateBuilder implements SqlBuilder {

    private SqlContext context;

    private String whereSql;

    private boolean buildFlag = false;

    public UpdateBuilder(Class<?> modelType) {
        this.context = new SqlContext(modelType);
    }

    @Override
    public String getSql() {
        BaseAssert.check(buildFlag, "尚未进行SQL构建，不能执行此操作！");
        BaseAssert.check(context.hasChangeColumns(), "参数不合法！没有可更新的列");

        StringBuilder sb = new StringBuilder("UPDATE `");
        sb.append(context.getMainTable());
        sb.append("` _t0");

        sb.append(context.getJoinSql());

        sb.append(" SET ");
        int count = 0;
        for (String column : context.getColumnList()) {
            if (count > 0) {
                sb.append(", ");
            }

            sb.append("_t0.`");
            sb.append(column);
            sb.append("`=?");
            count++;
        }

        if (StringUtils.isNotBlank(whereSql)) {
            sb.append(" WHERE ");
            sb.append(whereSql);
        }

        return sb.toString();
    }

    @Override
    public ParamStatementSetter getParams() {
        return context.getParamSetter();
    }

    public void build(Object model) throws Exception {
        buildPartial(null, null, null);
    }

    public void build(Object model, String... whereFields) throws Exception {
        buildPartial(model, null, whereFields, null);
    }

    public void build(Object model, String[] whereFields, String... ignoreFields) throws Exception {
        buildPartial(model, null, whereFields, ignoreFields);
    }

    public void buildPartial(Object model, String... partialFields) throws Exception {
        buildPartial(model, partialFields, null, null);
    }

    public void buildPartial(Object model, String[] partialFields, String... whereFields) throws Exception {
        buildPartial(model, partialFields, whereFields, null);
    }

    public void buildPartial(Object model, String[] partialFields, String[] whereFields, String... ignoreFields) throws Exception {
        buildFlag = true;

        boolean specifiedPartialFields = false;
        if (ArrayUtils.isNotEmpty(partialFields)) {
            specifiedPartialFields = true;
        }

        boolean specifiedIgnoreFields = false;
        if (ArrayUtils.isNotEmpty(ignoreFields)) {
            specifiedIgnoreFields = true;
        }

        SqlContextManager contextManager = SqlContextManager.newInstance(context);
        for (FieldObject fieldObject : context.getFieldList()) {
            if (specifiedIgnoreFields && ArrayUtils.contains(ignoreFields, fieldObject.getName())) {
                continue;
            }

            if (specifiedPartialFields && !ArrayUtils.contains(partialFields, fieldObject.getName())) {
                continue;
            }

            contextManager.setValue(fieldObject, model);
        }

        WhereBuilder whereBuilder = new WhereBuilder(context);
        whereBuilder.build(model, whereFields);
        whereSql = whereBuilder.getSql();
    }

    public void build(Object model, Condition condition) throws Exception {
        BaseAssert.notNull(condition, "condition为空");

        buildFlag = true;

        List<String> selectList = condition.getSelectItems().getSelectList();
        List<String> excludeList = condition.getSelectItems().getExcludeList();
        SqlContextManager contextManager = SqlContextManager.newInstance(context);
        for (FieldObject fieldObject : context.getFieldList()) {
            if (excludeList.size() > 0 && excludeList.contains(fieldObject.getName())) {
                continue;
            }

            if (selectList.size() > 0 && !selectList.contains(fieldObject.getName())) {
                continue;
            }
            contextManager.setValue(fieldObject, model);
        }

        WhereBuilder whereBuilder = new WhereBuilder(context);
        whereBuilder.build(condition);
        whereSql = whereBuilder.getSql();
    }

}
